/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 *
 */

import { spawnSync } from 'child_process';

import { FileUtil } from './file-util';

/**
 * keytool工具的包装器
 *
 * @since 2022/5/9
 */
export class KeytoolUtils {
  private storeFile: string;
  private storePassword: string;
  private keyAlias: string;
  private dn: string;
  private storetype = 'PKCS12';
  private keytool = 'keytool';
  private baseArgs: string[];

  constructor(storeFile: string, storePassword: string, keyAlias: string, dn: string) {
    this.storeFile = storeFile;
    this.storePassword = storePassword;
    this.keyAlias = keyAlias;
    this.dn = dn;
    this.baseArgs = ['-noprompt', '-keystore', this.storeFile, '-storepass', this.storePassword, '-storetype', this.storetype];
  }

  generateKeyPair(
    validity: number | undefined,
    keysize: number | undefined,
    keyalg: string | undefined,
    sigalg: string | undefined,
    startdate: Date | undefined,
  ) {
    const args = ['-genkeypair', '-alias', this.keyAlias, '-dname', this.dn];
    this.addArg(args, '-validity', validity);
    this.addArg(args, '-keysize', keysize);
    this.addArg(args, '-keyalg', keyalg);
    this.addArg(args, '-sigalg', sigalg);
    this.addArg(args, '-startdate', startdate);
    return this.execute(args);
  }

  requestCert(outfile: string) {
    const args = ['-certreq', '-alias', this.keyAlias, '-dname', this.dn];
    this.addArg(args, '-file', outfile);
    return this.execute(args);
  }

  generateCert(rfcoutput: boolean, validity: number, sigalg: string, startdate: Date, infile: string, outfile: string) {
    const args = ['-gencert', '-alias', this.keyAlias];
    this.addArg(args, '-dname', this.dn);
    this.addArg(args, '-validity', validity);
    this.addArg(args, '-sigalg', sigalg);
    this.addArg(args, '-startdate', startdate);
    this.addArg(args, '-infile', infile);
    this.addArg(args, '-outfile', outfile);

    if (rfcoutput) {
      args.push('-rfc');
    }

    const res = this.execute(args);
    FileUtil.deleteFile(infile);
    return res;
  }

  importCert(trustcacerts: boolean, infile: string) {
    const args = ['-importcert', '-alias', this.keyAlias];
    if (trustcacerts) {
      args.push('-trustcacerts');
    }
    this.addArg(args, '-file', infile);
    const res = this.execute(args);
    FileUtil.deleteFile(infile);
    return res;
  }

  private execute(args: string[]) {
    args = args.concat(this.baseArgs);
    const proc = spawnSync(this.keytool, args);
    if (proc.error) {
      return false;
    }
    return true;
  }

  private addArg(args: string[], name: string, value: undefined | string | number | boolean | Date) {
    if (value === undefined) {
      return;
    }
    if (value instanceof Date) {
      const time = `${value.getFullYear()}/${`0${value.getMonth() + 1}`.slice(-2)}/${`0${value.getDate()}`.slice(-2)} ${value.toTimeString().substring(0, 8)}`;
      args.push(name);
      args.push(time);
    } else {
      args.push(name);
      args.push(`${value}`);
    }
  }
}
